热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

技术讨论|基于基站定位APP开发实录

父母已经上了岁数,有时给他们手机打电话总是一直没人接听,搞得我很担心,怕出现意外。于是决定自己开发一

父母已经上了岁数,有时给他们手机打电话总是一直没人接听,搞得我很担心,怕出现意外。于是决定自己开发一款定位用APP为他们保驾护航。考虑到耗电问题,放弃GPS定位,研究了下基站定位技术,虽然定位精度不及GPS,但对于我的需求是足够的。

PS:本文仅用于技术讨论与分享,严禁用于任何非法用途。

一、基站定位简介

基站定位一般应用于手机用户,手机基站定位服务又叫做移动位置服务(LBS——Location Based Service),它是通过电信移动运营商的网络(如GSM网)获取移动终端用户的位置信息(经纬度坐标)。

基站定位的原理为:移动电话测量不同基站的下行导频信号,得到不同基站下行导频的TOA(Time of Arrival,到达时刻)或TDOA(Time Difference of Arrival,到达时间差),根据该测量结果并结合基站的坐标,一般采用三角公式估计算法,就能够计算出移动电话的位置。实际的位置估计算法需要考虑多基站(3个或3个以上)定位的情况,因此算法要复杂很多。一般而言,移动台测量的基站数目越多,测量精度越高,定位性能改善越明显。

二、开发思路

由于本次需求对定位精度要求不是特别高,就不采用多基点定位法了,本次采用单基点定位就可以了。单基点定位就是把与手机最新的基站认为手机的当前位置。

整个定位系统可以分为两部分:APP部分和离线电子地图。

下面我就详细说明每部分的功能。

1.APP详解。

APP以1分钟为周期捕获当前基站情报并存储在文件中,在一天结束的时候将当日的统计结果文件发送到指定邮箱中。

2,离线地图详解。

用户手动从邮箱中下载当日的定位文件,并手动导入到离线地图中,在地图中标记出当日的行走轨迹。

三、开发过程

APP篇

APP界面如下。

技术讨论 | 基于基站定位APP开发实录

APP机能中简单的部分我就不介绍了,难点是如何获得基站信息。

本次需要获得这些基站情报:网络类型、移动国家码、移动网络码、系统识别码、网络识别码、基站识别码。

下面是获得基站信息的代码。

private String ReadCellInfo() {
    TelephonyManager mTelephOnyManager= (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

    // 返回值MCC + MNC (注意:电信的mnc 对应的是 sid)
    String operator = mTelephonyManager.getNetworkOperator();
    if(operator!=null&&operator.length()==0){
return "手机无网络!";
    }
int mcc = -1;
    int mnc = -1;

    if(operator!=null&&operator.length()>3){
        mcc = Integer.parseInt(operator.substring(0, 3));
        mnc = Integer.parseInt(operator.substring(3));
    }

    StringBuffer cellinfo = new StringBuffer();

    //时间戳
    Calendar calendar = Calendar.getInstance();
    long unixTime = calendar.getTimeInMillis();

    int year = calendar.get(Calendar.YEAR) ;
    int mOnth= calendar.get(Calendar.MONTH)+1;
    int day = calendar.get(Calendar.DAY_OF_MONTH);
    int hour = calendar.get(Calendar.HOUR_OF_DAY); // 0-23
    int minute = calendar.get(Calendar.MINUTE);
    int secOnd= calendar.get(Calendar.SECOND);

    String mytime ="";
    mytime = String.format("%d%02d%02d %02d:%02d:%02d",year,month,day,hour,minute,second);
    cellinfo.append(mytime).append(",");
    
    //NetworkType
    int type = mTelephonyManager.getNetworkType();
    cellinfo.append(type +",");

    //需要判断网络类型,因为获取数据的方法不一样,
    if(type == TelephonyManager.NETWORK_TYPE_CDMA        // 电信cdma网
            || type == TelephonyManager.NETWORK_TYPE_1xRTT
            || type == TelephonyManager.NETWORK_TYPE_EVDO_0
            || type == TelephonyManager.NETWORK_TYPE_EVDO_A
            || type == TelephonyManager.NETWORK_TYPE_EVDO_B
            || type == TelephonyManager.NETWORK_TYPE_LTE){

// TIME,TYPE,MCC,MNC,SID,NID,BID
        CdmaCellLocation cdma = (CdmaCellLocation) mTelephonyManager.getCellLocation();
        if(cdma!=null){
            //Mobile country code:移动国家码
            sb.append("MCC = " + mcc +"\n");
            cellinfo.append(mcc +",");

      // Mobile Network Code:移动网络码 
            sb.append("MNC = " + mnc +"\n" );
            cellinfo.append(mnc +",");

            //System ID:系统识别码
            int sid = cdma.getSystemId();
            sb.append("SID = " + sid +"\n");
            cellinfo.append(sid +",");

            // Network ID:网络识别码
            int nid = cdma.getNetworkId();
            sb.append("NID = " + nid +"\n");
            cellinfo.append(nid +",");

            // Base Station ID:基站识别码
            int bid = cdma.getBaseStationId();
            sb.append("BID = " + bid +"\n");
            cellinfo.append(bid +",");
        }else{
            sb.append("can not get the CDMA CellLocation");
            cellinfo.append("can not get the CDMA CellLocation");
        }
    }else if(type == TelephonyManager.NETWORK_TYPE_UNKNOWN){
        cellinfo.append("电话卡不可用!");
    }

    String result = new String(cellinfo);
    return result;
}

每一分钟采集一次,并将统计的信息按【采样时间,网络类型、移动国家码、移动网络码、系统识别码、网络识别码、基站识别码】格式输出到文件中,其中一行为一条情报。

以下为某日生成的部分文件内容。

20180806 12:31:07,13,460,11,13858,13,8691,
20180806 12:32:07,13,460,11,13858,13,8691,
20180806 12:33:10,13,460,11,13858,13,8691,
20180806 12:34:22,13,460,11,13858,13,8691,
20180806 12:35:40,13,460,11,13858,13,8691,
20180806 12:36:40,13,460,11,13858,13,8691,
20180806 12:37:40,13,460,11,13858,13,8691,
20180806 12:38:41,13,460,11,13858,13,8691,
20180806 12:39:41,13,460,11,13858,13,8691,
20180806 12:40:41,13,460,11,13858,13,8691,
20180806 12:41:41,13,460,11,13858,13,8691,
20180806 12:42:41,13,460,11,13858,13,8691,
20180806 12:43:41,13,460,11,13858,13,8691,
20180806 12:44:41,13,460,11,13858,13,8691,
20180806 12:45:41,13,460,11,13858,13,8691,
20180806 12:46:42,13,460,11,13858,13,9000,
20180806 12:47:42,13,460,11,13858,13,9000,
20180806 12:48:42,13,460,11,13858,13,9000,
20180806 12:49:42,13,460,11,13858,13,9000,
20180806 12:50:42,13,460,11,13858,13,9000,
20180806 12:51:43,13,460,11,13858,13,9000,
20180806 12:52:43,13,460,11,13858,13,9000,
20180806 12:53:43,13,460,11,13858,13,9000,
20180806 12:54:43,13,460,11,13858,13,9000,
20180806 12:55:43,13,460,11,13858,13,9000,
20180806 12:56:43,13,460,11,13858,13,9000,
20180806 12:57:43,13,460,11,13858,13,9000,
20180806 12:58:43,13,460,11,13858,13,9000,
20180806 12:59:43,13,460,11,13858,13,8488,
20180806 13:00:44,13,460,11,13858,13,8488,
20180806 13:01:44,13,460,11,13858,13,8488,
20180806 13:02:44,13,460,11,13858,13,8488,

离线地图篇

本次离线地图是基于百度地图API实现的地图描画。

离线地图最核心内容将基站情报转换为基站的经纬度经度,再通过百度地图API进行轨迹点描画。

有很多网站会提供API可以获得基站的经纬度信息,但大部分都是收费的,好不容易找到了一家稳定且免费的API。

—————接口说明如下 —————

查询全国移动联通电信2G/3G/4G基站位置数据,收录数据总量1.2亿条

接口地址: http://api.cellocation.com:81/cell/

支持格式: CSV/JSON/XML

请求方式: GET

请求示例:  http://api.cellocation.com:81/cell/?mcc=460&mnc=1&lac=4301&ci=20986&output=xml

请求参数:

名称 类型 必填 说明
mcc int mcc国家代码:中国代码 460
mnc int mnc网络类型:0移动,1联通(电信对应sid),十进制
lac int lac(电信对应nid),十进制
ci int cellid(电信对应bid),十进制
coord string 坐标类型(wgs84/gcj02/bd09),默认wgs84
output string 返回格式(csv/json/xml),默认csv

返回数据格式:CSV

errcode,纬度,经度,精度半径,地址

errcode

0: 成功

10000: 参数错误

10001: 无查询结果

示例:

0,39.999024,116.476159,222,”北京市朝阳区望京街道北京市望京实验学校(宝星分校);阜安路与宏泰东街路口西231米”

————— 接口说明如下 结束 —————

最后,离线地图描画的最终效果如下图所示。

技术讨论 | 基于基站定位APP开发实录 四、结束语


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 我们


推荐阅读
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文讨论了编写可保护的代码的重要性,包括提高代码的可读性、可调试性和直观性。同时介绍了优化代码的方法,如代码格式化、解释函数和提炼函数等。还提到了一些常见的坏代码味道,如不规范的命名、重复代码、过长的函数和参数列表等。最后,介绍了如何处理数据泥团和进行函数重构,以提高代码质量和可维护性。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • 本文由编程笔记#小编整理,主要介绍了关于数论相关的知识,包括数论的算法和百度百科的链接。文章还介绍了欧几里得算法、辗转相除法、gcd、lcm和扩展欧几里得算法的使用方法。此外,文章还提到了数论在求解不定方程、模线性方程和乘法逆元方面的应用。摘要长度:184字。 ... [详细]
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
  • 1、Ipv4只能用于内网,外网只能用2、DNS:把域名解析成ip地址3、MAC地址就是物理地址(网卡序列号)   IP地址:电脑序列号4、不同电脑,微信之间互相通信,靠的是端口;  ... [详细]
author-avatar
淡逸幽悠
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有